package com.borderbears.backend.connection;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import javax.swing.AbstractListModel;
import javax.swing.ListModel;

import nanoxml.XMLElement;
import nanoxml.XMLParseException;

import com.borderbears.backend.util.Const;

public class ConnectionManager implements Const.ConnectionXML {

	private final Logger log = Logger.getLogger(getClass().getName());

	private final List<Connection> list = new ArrayList<Connection>();

	private static ConnectionManager instance;

	private ConnectionListModel listModel;

	public ListModel getListModel() {
		if (null == listModel) {
			listModel = new ConnectionListModel();
		}
		return listModel;
	}

	public void addConnection(final Connection c) {
		log.info("Adding connection:\n" + c.toString());
		listModel.addConnection(c);
	}

	public void removeConnection(final Connection c) {
		listModel.removeConnection(c);
	}

	/**
	 * Store the connection data in an XML formatted file.
	 *
	 * @param filename
	 */
	public void storeConnections(final String filename) {
		log.info("Attempting to store connections to: "+filename);
		final XMLElement xml = serializeConnections();
		final File f = new File(filename);
		try {
			final FileWriter writer = new FileWriter(f);
			xml.write(writer);
			writer.close();
			log.info("Connections stored");
		} catch (final IOException e) {
			log.warning("IO Error writing connections file: "+filename);
		}
	}

	/**
	 * Read connections from an xml file and store in the manager.
	 *
	 * @param filename
	 */
	public void readConnections(final String filename) {
		final File f = new File(filename);
		if (!f.exists()) {
			log.warning("Connections file not found");
			return;
		}
		try {
			final FileReader reader = new FileReader(new File(filename));
			final XMLElement xml = new XMLElement();
			xml.parseFromReader(reader);
			deserializeConnections(xml);
		} catch (final FileNotFoundException e) {
			log.warning("Connections file not found");
		} catch (final XMLParseException e) {
			log.warning("Error while parsing connections file: "+filename);
		} catch (final IOException e) {
			log.warning("IO Error while reading connections file: "+filename);
		}

	}

	private XMLElement serializeConnections() {
		final XMLElement xml = new XMLElement();
		xml.setName(ROOT_TAG);
		for (final Connection c : list) {
			final XMLElement x = c.serialize();
			xml.addChild(x);
		}

		return xml;
	}

	@SuppressWarnings("unchecked")
	private void deserializeConnections(final XMLElement xml) {
		list.clear();
		final List<XMLElement> children = xml.getChildren();
		for (final XMLElement e : children) {

			if (TAG_REMOTE_XML_CONNECTION.equals(e.getName())) {

				final String name = e.getStringAttribute(ATT_NAME);
				final String url = e.getStringAttribute(ATT_REMOTE_XML_URL);
				final RemoteXMLConnection c = new RemoteXMLConnection(name, url);
				list.add(c);

			} else if (TAG_LOCAL_FILE_CONNECTION.equals(e.getName())) {

			}
		}
		listModel.update();
	}

	public static ConnectionManager getInstance() {
		if (null == instance) {
			instance = new ConnectionManager();
		}
		return instance;
	}

	public class ConnectionListModel extends AbstractListModel {

		public void addConnection(final Connection c) {
			list.add(c);
			fireContentsChanged(this, list.size() - 2, list.size() - 1);
		}

		public void removeConnection(final Connection c) {
			list.remove(c);
			fireContentsChanged(this, 0, list.size() - 1);
		}

		public void update() {
			fireContentsChanged(this, 0, list.size()-1);
		}

		public Object getElementAt(final int arg0) {
			return list.get(arg0);
		}

		public int getSize() {
			return list.size();
		}

	}

}
